package br.ucb.cesbdao.model.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.JLabel;

import lombok.Getter;
import lombok.Setter;

import org.apache.log4j.Logger;

import br.ucb.cesbdao.beans.Trabalhador;
import br.ucb.cesbdao.beans.Atendimento;
import br.ucb.cesbdao.beans.Encaminhamento;
import br.ucb.cesbdao.beans.Grupo;
import br.ucb.cesbdao.beans.TipoAtendimento;
import br.ucb.cesbdao.enuns.EnumPreferencial;
import br.ucb.cesbdao.model.AtendimentoModel;
import br.ucb.cesbdao.model.EncaminhamentoModel;
import br.ucb.cesbdao.model.TipoAtendimentoModel;
import br.ucb.cesbdao.model.TrabalhadorModel;
import br.ucb.cesbdao.persistencia.dao.AtendimentoDAO;
import br.ucb.cesbdao.persistencia.factory.FactoryConnection;
import br.ucb.cesbdao.persistencia.factory.FactoryDAO;
import br.ucb.cesbdao.relatoriosDTO.TrabalhadorDTO;
import br.ucb.cesbdao.relatoriosDTO.AtendimentoDetalheDTO;
import br.ucb.cesbdao.servicos.Servicos;

public class AtendimentoModelImpl implements AtendimentoModel{

	private Logger logger = Servicos.carregaLog(AtendimentoModelImpl.class);
	@Getter @Setter
	private AtendimentoDAO dao;

	public AtendimentoModelImpl() {
	}

	@Override
	public void addAtendimento(Atendimento atendimento) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			getDao().addAtendimento(atendimento);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}

	@Override
	public void addAtendimento(Atendimento atendimento, Date date) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			getDao().addAtendimento(atendimento, date);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}

	@Override
	public void addAtendimentoChegada(Atendimento atendimento) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			getDao().addAtendimentoChegada(atendimento);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}

	@Override
	public void delAtendimento(int id) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			getDao().delAtendimento(id);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}

	@Override
	public Atendimento getByIdAtendimento(int id) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getByIdAtendimento(id);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<Atendimento> getAll() {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getAll();
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<Atendimento> getEspera() {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getEspera();
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<Atendimento> getByChavePessoa() {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getByChavePessoa();
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public boolean isVerificaEmAtendimento(Integer idPaciente) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().isVerificaEmAtendimento(idPaciente);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return false;
	}

	@Override
	public boolean isVerificaEmAtendimentoAFI(String cpf) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().isVerificaEmAtendimentoAFI(cpf);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return false;
	}

	@Override
	public void registraEntrada(int id, String cpf) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			getDao().registraEntrada(id, cpf);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}

	@Override
	public void upTipo(int id, int tipo) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			getDao().upTipo(id, tipo);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}

	@Override
	public void registraDesistencia(int id) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			getDao().registraDesistencia(id);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}

	@Override
	public ArrayList<Atendimento> getEmAndamento() {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getEmAndamento();
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public void registraHorarioEntrada(int id) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			getDao().registraHorarioEntrada(id);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}

	@Override
	public void registraHorarioMarcacao(int id) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			getDao().registraHorarioMarcacao(id);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}

	@Override
	public void registraSaida(int id) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			getDao().registraSaida(id);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}

	@Override
	public ArrayList<Atendimento> getByDataHoje() {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getByDataHoje();
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<Atendimento> getByData(Date date) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getByData(date);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<Atendimento> getDesistentes() {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getDesistentes();
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<Atendimento> getByAno(int ano) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getByAno(ano);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<Atendimento> getByPeriodo(Date dateInicio, Date dateFim) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getByPeriodo(dateInicio, dateFim);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<Atendimento> getByPeriodoAndAFI(Date dateIni, Date dateFim, String cpf) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getByPeriodoAndAFI(dateIni, dateFim, cpf);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<TrabalhadorDTO> getByPeriodoAndGrupo(Date dataInicio, Date dataFim, Grupo grupo) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getByPeriodoAndGrupo(dataInicio, dataFim, grupo);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<AtendimentoDetalheDTO> getByPeriodoAndAtendido(Date dataInicio, Date dataFim, Integer id) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return criaListaAtendimentoDetalheDTO(getDao().getByPeriodoAndAtendido(dataInicio, dataFim, id));
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<AtendimentoDetalheDTO> getByPeriodoDetalhe(Date dataInicio, Date dataFim) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return criaListaAtendimentoDetalheDTO(getDao().getByPeriodoDetalhe(dataInicio, dataFim));
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}
	
	@Override
	public ArrayList<AtendimentoDetalheDTO> getByPeriodoAndAtendidoByAFI(Date dataInicio, Date dataFim, Integer id, Trabalhador atendente) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return criaListaAtendimentoDetalheDTO(getDao().getByPeriodoAndAtendidoByAFI(dataInicio, dataFim, id, atendente));
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}
	
	private ArrayList<AtendimentoDetalheDTO> criaListaAtendimentoDetalheDTO(ResultSet rs) throws SQLException {
		ArrayList<AtendimentoDetalheDTO> detalheAtendimentos = new ArrayList<AtendimentoDetalheDTO>();
		while(rs.next()){
			ArrayList<Encaminhamento> encaminhamentos = getEncaminhamentos(rs);
			ArrayList<TipoAtendimento> tipoAtendimentos = getTipoEncaminhamentos(rs);
			Trabalhador afi = getTrabalhadorParaRelatorio(rs);
			detalheAtendimentos.add(criaAtendimentoDTO(rs, afi, encaminhamentos, tipoAtendimentos));
		}
		return detalheAtendimentos;
	}
	
	public AtendimentoDetalheDTO criaAtendimentoDTO(ResultSet rs, Trabalhador afi, ArrayList<Encaminhamento> encaminhamentos, ArrayList<TipoAtendimento> tipoAtendimentos) {
		try{
			return new AtendimentoDetalheDTO(
					rs.getString("nomePessoa"),
					rs.getString("sexo"),
					afi.getNome() == null ? "Nenhum AFI" :afi.getNome(),
					rs.getString("data"),
					rs.getString("horarioChegada") == null ? "-":rs.getString("horarioChegada"),
					rs.getString("horarioEntrada") == null ? "-":rs.getString("horarioEntrada"),
					rs.getString("horarioSaida") == null ? "-":rs.getString("horarioSaida"),
					EnumPreferencial.getPreferenciaById(rs.getInt("preferencia")),
					encaminhamentos,
					tipoAtendimentos);
		} catch (SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		return null;
	}
	
	private Trabalhador getTrabalhadorParaRelatorio(ResultSet rs) {
		try {
			TrabalhadorModel trabModel = new TrabalhadorModelImpl();
			return trabModel.consultaTrabalhadorByCpf(rs.getString("cpf"));
		} catch (SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		return null;
	}

	private ArrayList<TipoAtendimento> getTipoEncaminhamentos(ResultSet rs) {
		try {
			TipoAtendimentoModel tpModel = new TipoAtendimentoModelImpl();
			return tpModel.getByIdAtendimento(rs.getInt("idAtendimento"));
		} catch (SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		return null;
	}

	private ArrayList<Encaminhamento> getEncaminhamentos(ResultSet rs) {
		try {
			EncaminhamentoModel encModel = new EncaminhamentoModelImpl();
			return encModel.getByIdAtendimento(rs.getInt("idAtendimento"));
		} catch (SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public Integer getQuantAtendimentoAFI(String cpf) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getQuantAtendimentoAFI(cpf);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public ArrayList<Atendimento> getByAfiDate(Trabalhador atendente, Date date) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getByAfiDate(atendente, date);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public Object getQuantAtendimentoAfiDate(String cpf, Date date) {
		try{
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			return getDao().getQuantAtendimentoAfiDate(cpf, date);
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
		return null;
	}

	@Override
	public void qtdRestam(JLabel lblRestam) {
		DecimalFormat dc = new DecimalFormat("00");
		try {
			setDao(FactoryDAO.getDaoAtendimento(FactoryConnection.getInstance().criaConexao()));
			lblRestam.setText(String.valueOf(dc.format(getDao().getEspera().size())));
		} catch (ClassNotFoundException | SQLException e) {
			logger.error(e.getMessage());
			e.printStackTrace();
		} finally {
			FactoryConnection.getInstance().closeConexao(getDao().getConexao());
		}
	}
}
